#include <GL/glut.h>
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <time.h>
#include "glm.h"

/********************************
 *           TypeDefs           *
 ********************************/

struct STRUCT_PONTO {
  GLfloat x;
  GLfloat y;
  GLfloat z;
};

typedef struct STRUCT_PONTO Ponto3D;

#define X 0
#define Y 1

/********************************
 *        WINDOW DEFINES        *
 ********************************/
#define PAGORACER_WIDTH 400
#define PAGORACER_HEIGHT 300

/********************************
 *          BOOL DEFINES        *
 ********************************/

#define FALSE  0
#define TRUE   1

/********************************
 *        INIT_MOV_CARRO        *
 ********************************/

#define INIT_MOV_CARRO 0.0

/********************************
 *       INIT_PROF_CARR         *
 ********************************/

#define INIT_PROF_PIST 0.0

/********************************
 *           Y zerado           *
 ********************************/

#define Y_INICIAL -50.0

/********************************
 *       VELOCIDADE / 10 ms     *
 ********************************/

#define VEL_INICIAL 0.0

/********************************
 *          ACELERACAO          *
 ********************************/

#define ACELERACAO 0.0005
#define DESACELERACAO -0.001
#define FREIO -0.0015

/********************************
 *          VELOCIDADES         *
 ********************************/

#define VEL_MIN 0.0
#define VEL_MAX 0.2
#define VIRA_CARRO 0.2

/********************************
 *            DIFFS             *
 ********************************/

#define DIFF_ESQUERDA  1
#define DIFF_RETA      2
#define DIFF_DIREITA   3

/*************************************
 *   NUMERO DE PONTOS PARA A CURVA   *
 *************************************/

#define NUM_PONTOS 11

/********************************
 *       KEYBOARD DEFINES       *
 ********************************/

#define NUM_TECLAS     4

#define TECLA_ESQUERDA 0
#define TECLA_DIREITA  1
#define TECLA_CIMA     2
#define TECLA_BAIXO    3

/********************************
 *      TAMANHO DA CURVA        *
 ********************************/

#define TAMANHO_CURVA 15.0

/********************************
 *      DISTANCIA DOS PONTOS    *
 *           ESPARSOS           *
 ********************************/

#define DIST_PONTOS_ESPARSOS 20.0

/********************************
 * DISTANCIA DOS PONTOS DE MEIO *
 * PARA OS PONTOS DE PISTA      *
 ********************************/

#define DIST_ESPAR_MEIO_Y   DIST_PONTOS_ESPARSOS/2.0

/********************************
 *   DISTANCIA ENTRE LADOS DA   *
 *            PISTA             *
 ********************************/

#define DIST_ENTRE_BORDAS_X 10.0

/********************************
 *  DISTANCIA DO MEIO DA PISTA  *
 *          PARA BORDA          *
 ********************************/

#define DIST_MEIO_BORDA_X DIST_ENTRE_BORDAS_X / 2.0

/********************************
 *       VALORES DE PASSO       *
 ********************************/

#define NUM_PASSOS 20
#define TAM_PASSO  DIST_PONTOS_ESPARSOS / ((GLfloat) NUM_PASSOS)


/********************************
 * VALORES PARA DESENHAR FAIXAS *
 ********************************/

#define NUM_FAIXAS NUM_PONTOS*2
#define DIST_FAIXAS NUM_PASSOS/2


/********************************
 *    O VALOR CLASSICO DE Z     *
 ********************************/

#define Z 0.0

/********************************
 *         FIM_DESENHADO        *
 ********************************/

#define NUM_DESENHADOS 9
#define FIM_DESENHADO  NUM_DESENHADOS*NUM_PASSOS

/********************************
 *     VALORES DE INTERVALO     *
 ********************************/

#define INICIO_ESQ    1
#define FIM_ESQ       4
#define INICIO_RETA   4
#define FIM_RETA      9
#define INICIO_DIR    9
#define FIM_DIR      11

/********************************
 *           X maximo           *
 ********************************/

#define X_MAXIMO 70.0

/*************************************
 *   NUMERO DE PONTOS PARA A CURVA   *
 *            DESENHADA              *
 *************************************/

#define TOTAL_PONTOS NUM_PASSOS*NUM_PONTOS

/*************************************
 *        DADOS DA CAMERA 1          *
 *************************************/

#define CAMERA_1_EYE_X      MovCarro
#define CAMERA_1_EYE_Y          -2.0
#define CAMERA_1_EYE_Z           7.0
#define CAMERA_1_CENTER_X   MovCarro
#define CAMERA_1_CENTER_Y       10.0
#define CAMERA_1_CENTER_Z        0.0
#define CAMERA_1_UP_X            0.0
#define CAMERA_1_UP_Y            0.0
#define CAMERA_1_UP_Z            1.0

/*************************************
 *        DADOS DA CAMERA 2          *
 *************************************/

#define CAMERA_2_EYE_X               MovCarro
#define CAMERA_2_EYE_Y                    2.0
#define CAMERA_2_EYE_Z                    1.0
#define CAMERA_2_CENTER_X   MovCarro+x_centro
#define CAMERA_2_CENTER_Y        1.5+y_centro
#define CAMERA_2_CENTER_Z                 0.0
#define CAMERA_2_UP_X                     0.0
#define CAMERA_2_UP_Y                     0.0
#define CAMERA_2_UP_Z                     1.0
#define DIST_EYE_CENTER                  30.0

/*************************************
 *           DADOS DE COR            *
 *************************************/

#define CEU_RED      0.8
#define CEU_GREEN    0.8
#define CEU_BLUE     1.0
#define CEU_ALPHA    0.0
#define GRAMA_RED    0.0
#define GRAMA_GREEN  0.3
#define GRAMA_BLUE   0.0
#define PISTA_RED    0.2
#define PISTA_GREEN  0.2
#define PISTA_BLUE   0.2
#define CARRO_RED    0.0
#define CARRO_GREEN  0.5
#define CARRO_BLUE   0.5

/*************************************
 *        DEFINICOES DO PLANO        *
 *************************************/

#define PLANO_INICIO_X -200.0
#define PLANO_INICIO_Y -200.0
#define PLANO_FIM_X     200.0
#define PLANO_FIM_Y     200.0

/*************************************
 *        DIMENSOES DO CARRO         *
 *************************************/

#define CARRO_TAM_X 1.0
#define CARRO_TAM_Y 2.0
#define CARRO_TAM_Z 1.0
#define CUBE        1.0

#define DIST_ORIG_CARRO 0.0

/*************************************
 *       DADOS DA PERSPECTIVA        *
 *************************************/

#define PERSP_ANGLE 70.0
#define PERSP_NEAR  1.0
#define PERSP_FAR   50.0

/*************************************
 *         ROTACAO NO EIXO Z         *
 *************************************/

#define ROTA_Z_X 0.0
#define ROTA_Z_Y 0.0
#define ROTA_Z_Z 1.0

/*************************************
 *                ANGULO             *
 *************************************/

#define ANGULO_INICIAL          0.0
#define SOMA_ANGULO             0.7
#define SUBTRAI_ANGULO -SOMA_ANGULO
#define ANG_MAX                90.0
#define ANG_MIN            -ANG_MAX
#define SENO_0                  0.0
#define COSSENO_0               1.0
#define ANGULO_SOL_INICIAL    360.0

/*************************************
 *              CAMERAS              *
 *************************************/

#define CAMERA_1 0
#define CAMERA_2 1
#define CAMERA_3 2

/*************************************
 *      CONSTANTES MATEMATICAS       *
 *************************************/

#define PI 3.141592653589793

/********************************
 *       Global Variables       *
 ********************************/

extern GLfloat seno;
extern GLfloat cosseno;
extern int DiffFinal;
extern int Camera;
extern GLfloat MovCarro;

extern GLfloat ProfundidadePista;
extern GLfloat MovePista;
extern GLfloat AnguloAtual;
extern GLfloat SolAngulo;

extern Ponto3D PontosEsparsos[NUM_PONTOS];
extern Ponto3D PontosDeMeio[NUM_PONTOS];
extern Ponto3D PontosDePista[TOTAL_PONTOS];

extern char teclas[NUM_TECLAS];

extern GLMmodel * carro1;
extern GLMmodel * carro2;
extern GLMmodel * carro3;

/********************************
 *           Functions          *
 ********************************/

/*************************************************
 *****               keyboard.c              *****
 *************************************************/

/* Evaluate Key Presses */
void PressKeyboardKey(int key);

/* Evaluate Key Presses */
void PressKeyboard(int key, int x, int y);

/* Evaluate Key Unpresses */
void UnpressKeyboard(int key, int x, int y);

/*************************************************
 *****                 init.c                *****
 *************************************************/

/* Initialize data */
void InitData(int argc, char ** argv);

/*************************************************
 *****               bezier.c                *****
 *************************************************/

/* Calculates Bezier Curve */
GLfloat CalculaBezier (GLfloat t, GLfloat a1, 
		       GLfloat a2, GLfloat a3);

/*************************************************
 *****               redefine.c              *****
 *************************************************/

/* Redefine toda a pista */
void RedefinePista();

/*************************************************
 *****               render.c                *****
 *************************************************/

/* Renderiza o Pagoracer */
void RenderPagoracer(void);

/*************************************************
 *****            temporazida.c              *****
 *************************************************/

/* Funcao para temporizar desenhos */
void TemporizaPagoracer(int val);

/*************************************************
 *****              reshape.c                *****
 *************************************************/
void ReshapePagoracer(int w, int h);
